package logic

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/olivere/elastic/v7"
	"goods_srv/global"
	"goods_srv/goods_proto"
	"goods_srv/model"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// 商品列表
func (g *GoodsServer) GoodsList(ctx context.Context, in *goods_proto.GoodsFilterRequest) (*goods_proto.GoodsListResponse, error) {
	goodsListResponse := &goods_proto.GoodsListResponse{}
	var goods []model.Goods
	q := elastic.NewBoolQuery()
	//实例化一个商品表
	localDB := global.DB.Model(model.Goods{})
	//判断是否是关键字
	if in.KeyWords != "" {
		localDB.Where("name like ?", "%"+in.KeyWords+"%")
		q = q.Must(elastic.NewMultiMatchQuery(in.KeyWords, "name", "goods_brief"))
	}
	//是否是热销
	if in.IsHot {
		localDB.Where(model.Goods{IsHot: true})
		q = q.Filter(elastic.NewTermQuery("is_hot", in.IsHot))
	}
	//是否是新品
	if in.IsNew {
		localDB.Where(model.Goods{IsNew: true})
		q = q.Filter(elastic.NewTermQuery("is_new", in.IsNew))
	}
	//商品最低价
	if in.PriceMin > 0 {
		localDB.Where("shop_price >= ?", in.PriceMin)
		q = q.Filter(elastic.NewTermQuery("shop_price", in.PriceMin))
	}
	//商品最高价
	if in.PriceMax > 0 {
		localDB.Where("shop_price <=?", in.PriceMax)
		q = q.Filter(elastic.NewTermQuery("shop_price", in.PriceMax))
	}
	//品牌条件筛选
	if in.Brand > 0 {
		localDB.Where("brands_id =?", in.Brand)
		q = q.Filter(elastic.NewTermQuery("brands_id", in.Brand))
	}
	//通过category查询商品
	var subQuery string
	//不是顶级分类时(顶级分类为0)
	if in.TopCategory > 0 {
		//实例化商品分类
		var category model.Category
		categoryIds := make([]interface{}, 0)
		//判断是否是顶级分类
		if result := global.DB.First(&category, in.TopCategory); result.RowsAffected == 0 {
			return nil, errors.New("商品分类不存在")
		}
		if category.Level == 1 { //如果等级为一级,查询查询等级一下的等级二下的第三等级
			subQuery = fmt.Sprintf("select id from category where parent_category_id in (select id from category WHERE parent_category_id=%d)", in.TopCategory)
		} else if category.Level == 2 { //如果等级为二级,查询等级为二级下面的等级三
			subQuery = fmt.Sprintf("select id from category where parent_category_id =%d", in.TopCategory)
		} else if category.Level == 3 { //如果是等级三查询等级三下面的数据
			subQuery = fmt.Sprintf("select id from category where id =%d", in.TopCategory)
		}
		//直接查询Goods表中category_id的数据
		localDB = localDB.Where(fmt.Sprintf("category_id  in(%s)", subQuery))
		type Result struct {
			Id int32
		}
		var results []Result
		global.DB.Model(&model.Category{}).Raw(subQuery).Scan(&results)
		for _, res := range results {
			categoryIds = append(categoryIds, res.Id)
		}
		q = q.Filter(elastic.NewTermsQuery("category_id", categoryIds...))
	}
	//es搜索
	switch {
	case in.PagePerNums > 100:
		in.PagePerNums = 100
	case in.PagePerNums <= 0:
		in.PagePerNums = 100
	}
	offset := (in.Pages - 1) * in.PagePerNums
	searchResult, err := global.EsClient.Search().
		Index(model.EsGoods{}.GetIndexName()). // search in index "twitter"
		Query(q).                              // specify the query
		//Sort("user", true).                          // sort by "user" field, ascending
		From(int(offset)).Size(int(in.PagePerNums)). // take documents 0-9
		Pretty(true).                                // pretty print request and response JSON
		Do(ctx)                                      // execute
	if err != nil {
		return nil, err
	}
	goodsIds := make([]int32, 0)
	goodsListResponse.Total = int32(searchResult.Hits.TotalHits.Value)
	for _, hit := range searchResult.Hits.Hits {
		good := model.EsGoods{}
		json.Unmarshal(hit.Source, &good)
		goodsIds = append(goodsIds, good.Id)
	}
	result := localDB.Preload("Category").Preload("Brands").Find(&goods, goodsIds)
	if result.Error != nil {
		return nil, result.Error
	}

	////查询总条数
	//var count int64
	//localDB.Count(&count)
	////赋值
	//goodsListResponse.Total = int32(count)
	////查询Goods表中的满足上述条件的数据(缓存Category和Brands表中数据)
	//result := localDB.Preload("Category").Preload("Brands").Scopes(Paginate(int(in.Pages), int(in.PagePerNums))).Find(&goods)
	//if result.Error != nil {
	//	return nil, result.Error
	//}
	//循环遍历追加到切片中
	for _, good := range goods {
		goodsInfoResponse := ModelToResponse(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	//返回数据
	return goodsListResponse, nil
}

// 根据ID批量查询商品信息
func (g *GoodsServer) BatchGetGoods(ctx context.Context, in *goods_proto.BatchGoodsIdInfo) (*goods_proto.GoodsListResponse, error) {
	//protobuf格式的
	goodsListResponse := &goods_proto.GoodsListResponse{}
	//商品数据
	var goods []model.Goods
	//通过ID查询用户信息
	result := global.DB.Where(in.Id).Find(&goods)
	if result.Error != nil {
		return nil, result.Error
	}
	//查询总条数
	var count int64
	result.Count(&count)
	goodsListResponse.Total = int32(count)
	//循环遍历追加数据
	for _, good := range goods {
		goodsInfoResponse := ModelToResponse(good)
		goodsListResponse.Data = append(goodsListResponse.Data, &goodsInfoResponse)
	}
	return goodsListResponse, nil
}

// 商品详情
func (g *GoodsServer) GetGoodsDetail(ctx context.Context, in *goods_proto.GoodInfoRequest) (*goods_proto.GoodsInfoResponse, error) {
	var goods model.Goods
	if result := global.DB.Preload("Category").Preload("Brands").First(&goods, in.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "商品不存在")
	}
	goodsInfoResponse := ModelToResponse(goods)
	return &goodsInfoResponse, nil
}

// 新增商品
func (g *GoodsServer) CreateGoods(ctx context.Context, in *goods_proto.CreateGoodsInfo) (*goods_proto.GoodsInfoResponse, error) {
	var category model.Category
	if result := global.DB.First(&category, in.CategoryId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "商品分类不存在")
	}
	var brands model.Brands
	if result := global.DB.First(&brands, in.BrandId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "品牌不存在")
	}
	goods := model.Goods{
		CategoryID:      in.CategoryId,
		Category:        category,
		BrandsID:        in.BrandId,
		Brands:          brands,
		OnSale:          in.OnSale,
		ShipFree:        in.ShipFree,
		IsNew:           in.IsNew,
		IsHot:           in.IsHot,
		Name:            in.Name,
		GoodsSn:         in.GoodsSn,
		MarketPrice:     in.MarketPrice,
		ShopPrice:       in.ShopPrice,
		GoodsBrief:      in.GoodsBrief,
		Images:          in.Images,
		DescImages:      in.DescImages,
		GoodsFrontImage: in.GoodsFrontImage,
	}
	tx := global.DB.Save(&goods)
	if tx.Error != nil {
		return nil, status.Errorf(codes.Internal, "商品新增失败")
	}
	goodsInfoResponse := ModelToResponse(goods)
	return &goodsInfoResponse, nil
}

// 删除商品
func (g *GoodsServer) DeleteGoods(ctx context.Context, in *goods_proto.DeleteGoodsInfo) (*goods_proto.Empty, error) {
	var goods model.Goods
	tx := global.DB.Delete(&goods, in.Id)
	if tx.Error != nil {
		return nil, status.Errorf(codes.Internal, "商品删除失败")
	}
	return &goods_proto.Empty{}, nil
}

// 修改商品信息
func (g *GoodsServer) UpdateGoods(ctx context.Context, in *goods_proto.CreateGoodsInfo) (*goods_proto.Empty, error) {
	var goods model.Goods
	if result := global.DB.First(&goods, in.Id); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "商品不存在")
	}
	var category model.Category
	if result := global.DB.First(&category, in.CategoryId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "商品分类不存在")
	}
	var brands model.Brands
	if result := global.DB.First(&brands, in.BrandId); result.RowsAffected == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "品牌不存在")
	}
	goods.CategoryID = in.CategoryId
	goods.Category = category
	goods.BrandsID = in.BrandId
	goods.Brands = brands
	goods.OnSale = in.OnSale
	goods.ShipFree = in.ShipFree
	goods.IsNew = in.IsNew
	goods.IsHot = in.IsHot
	goods.Name = in.Name
	goods.GoodsSn = in.GoodsSn
	goods.MarketPrice = in.MarketPrice
	goods.ShopPrice = in.ShopPrice
	goods.GoodsBrief = in.GoodsBrief
	goods.Images = in.Images
	goods.DescImages = in.DescImages
	goods.GoodsFrontImage = in.GoodsFrontImage
	tx := global.DB.Updates(&goods)
	if tx.Error != nil {
		return nil, status.Errorf(codes.Internal, "商品更新失败")
	}
	return &goods_proto.Empty{}, nil
}
